/** \file    Imagine.cpp
  * \brief   Creates image with representation of segmentation.
  * \date    2001 - 2003
  * \author  Fedor Chelnokov
  * \version $Header: /home/cscom1r4/cvsroot/cs/segm/src/Imagine.cpp,v 1.1 2004/05/20 09:11:46 cscom1r4 Exp $
  */

#include "segm/Segmentation.h"
#include "imglib/image.h"

//predicates

static inline bool all( int /*sgIndex*/ ) 
	{ return true; }

class ForeignPredicate
{
public:
	ForeignPredicate( const Segmentation &s ) : _s(s) {}
	bool operator()( int sgIndex ) const
		{ return _s.segmentByIndex(sgIndex).foreign; }

private:
	const Segmentation &_s;
};

class GivenPredicate
{
public:
	GivenPredicate( const BoolArr &b ) : _b(b) {}
	bool operator()( int sgIndex ) const
		{ return _b[sgIndex]; }

private:
	const BoolArr &_b;
};

template< class P >
void imagineSegmentation_impl(byte_image & img, const Segmentation & s, const P & p)
{
	int w = s.width();
	int h = s.height();
	img.resize(w, h);
	int x,y;
	for( y = 0; y != h; ++y ) {
		for( x = 0; x != w; ++x ) {
			int i = s.segmentIndex(x,y);
			img(x,y) = ( i==-1 || !p(i) ) ? small_byte_color() : s.segmentByIndex(i).color;
		}
	}
}

void Segmentation::imagineSegmentation(byte_image & img) const
{
	imagineSegmentation_impl(img, *this, &all);
}

void Segmentation::imagineForeignSegments(byte_image & img) const
{
	imagineSegmentation_impl(img, *this, ForeignPredicate(*this));
}

void Segmentation::imagineGivenSegments(byte_image & img, const BoolArr & show) const
{
	imagineSegmentation_impl(img, *this, GivenPredicate(show));
}

template< class P >
void imagineDisplacedSegmentation_impl(byte_image & img, const Segmentation & s, const P & p)
{
	int w = s.width();
	int h = s.height();
	img.resize(w, h);
	img::fill(img, byte_color());
	int_point src;
	//loops by coordinates of sorce image
	for( src.y = 0; src.y != h; ++src.y ) {
		for( src.x = 0; src.x != w; ++src.x ) {
			int i = s.segmentIndex(src.x,src.y);
			if (i==-1 || !p(i))
				continue;
			const Segment *g = s.pSegmentByIndex(i);
			int_point itgt = src + g->adisplacement();
			if (itgt.x < 0 || itgt.y < 0 || itgt.x >= w || itgt.y >= h) 
				continue;
			size_point tgt = itgt;
			img[tgt] = int2color(color2int(img[tgt]) | color2int(g->color));
		}
	}
}

void Segmentation::imagineDisplacedSegmentation(byte_image & img) const
{
	imagineDisplacedSegmentation_impl(img, *this, &all);
}

void Segmentation::imagineGivenDisplacedSegments(byte_image & img, const BoolArr & show) const
{
	imagineDisplacedSegmentation_impl(img, *this, GivenPredicate(show));
}
